package at.ac.univie.bi.transformation.controller;

import java.io.File;
import java.io.IOException;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import at.ac.univie.bi.transformation.model.output.ValueObject;

public class ExportController {
	
	public final String XML_OUTPUT_FILE = "/home/daniel/workspace/businessintelligence/export.xml";
	public final String XSD_FILE = "WorkflowLog.xsd";
	
	
	public void exportDB(){
		try {
			 
			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
	 
			// root elements
			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement("WorkflowLog");
			doc.appendChild(rootElement);
			
			Element dataElement = doc.createElement("Data");
			dataElement.setNodeValue("JSON");
			Element attributeElement = doc.createElement("Attribute");
			
			String jsonString = getDataAsJsonString();
			
			attributeElement.setTextContent(jsonString);
			Attr attr = doc.createAttribute("name");
			attr.setValue("json");
			attributeElement.setAttributeNode(attr);
			dataElement.appendChild(attributeElement);
			
			
			Element sourceElement = doc.createElement("Source");
			attr = doc.createAttribute("program");
			attr.setValue("sql");
			sourceElement.setAttributeNode(attr);
			dataElement.appendChild(attributeElement);
			
			Element processElement = doc.createElement("Process");
			attr = doc.createAttribute("id");
			attr.setValue("1");
			processElement.setAttributeNode(attr);
			
			
			rootElement.appendChild(dataElement);
			rootElement.appendChild(sourceElement);
			rootElement.appendChild(processElement);
	 
			// write the content into xml file
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(new File(XML_OUTPUT_FILE));
	 
			// Output to console for testing
			// StreamResult result = new StreamResult(System.out);
	 
			transformer.transform(source, result);
	 
			System.out.println("File saved!");
	 
		  } catch (ParserConfigurationException pce) {
			pce.printStackTrace();
		  } catch (TransformerException tfe) {
			tfe.printStackTrace();
		  }
	}
	
	public String getDataAsJsonString(){
		ValueObject json = new ValueObject();
		return convertToJsonString(json);
	}
	
	public String convertToJsonString(Object object){

		ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
		StringBuilder json = new StringBuilder();
		try {
			json.append(ow.writeValueAsString(object));
		} catch (JsonGenerationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return json.toString();
	}
	
	public void validateOutput(){
		validateXMLSchema(XSD_FILE, XML_OUTPUT_FILE);
	}	
	
	public static boolean validateXMLSchema(String xsdPath, String xmlPath){
        
        try {
            SchemaFactory factory = 
                    SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

        	File xsd = new File("resources/"+xsdPath);
            
            Schema schema = factory.newSchema(xsd);
            Validator validator = schema.newValidator();
            validator.validate(new StreamSource(new File(xmlPath)));
        } catch (SAXException e) {
            System.out.println("SAX Exception: "+e.getMessage());
            return false;
        } catch (IOException e) {
            System.out.println("IO Exception: "+e.getMessage());
            return false;
        }
        return true;
    }
}
